/*
    YmsgIRC - Program enabling YMSG chat clients to use IRC
    Copyright (C) 2011 Crash Daemonicus ( crashenator -at- gmail.com )

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "YMSG.h"

using namespace std;



void YMSG::init(int mode)
{
    if(mode==0 || mode==1)
    {
        memcpy(head.Ref.signature,YMSG_SIGNATURE,sizeof(head.Ref.signature));
        head.Ref.version=0;
        head.Ref.vendorID=0;
        head.Ref.status=0;
        head.Ref.contentLength=0;
        head.Ref.sessionID=0;
        head.Ref.type=0;
        head.availRef=true;
        head.availDat=false;
        head.translate();//translate Dat from Ref (prev 2 cond)
    }
}
void YMSG::init(unsigned short ver,unsigned short vid,unsigned int sid)
{   
    init();
    head.Ref.version=ver;
    head.Ref.vendorID=vid;
    head.Ref.sessionID=sid;
    head.availRef=true;
    head.availDat=false;
    head.translate();
    
    name="YMSG";
    pmToChat=false;
    stripYmsgFormats=true;
    nickRefresh=true;
}
YMSG::YMSG(unsigned short ver,unsigned short vid,unsigned int sid)
{
    init(ver,vid,sid);
}
YMSG::YMSG()
{
    init(17,0,0);
}
YMSG::~YMSG(){ ; }

void YMSG::debug(){  head.print(); }

string YMSG::getdata(const string& data,int num)
{
    string s="";
    if( data.length()<1 || num<0){
        throw 1;
        return s;
    }
    try{
        YmsgField f=GetField(data,num);
        f.process();
        if(f.valid) s=f.value;
        return s;
    }
    catch(...){
        throw 2;
        return s;
    }
    return s;
}


bool YMSG::setuser(const YmsgField& f)
{
    username=f.value;
    return true;
}
bool YMSG::setuser(const string& data,int num)
{
    try{
        username=getdata(data,num);
        return true;
    }
    catch(...){
        return false;
    }
    return false;//unreachable
}
bool YMSG::setuser(const YmsgItem& content,int num,int occur)
{
	
	vector<YmsgField>::const_iterator it=content.find(num,occur);
	if(it==content.fields.end()) return false;
	username=(*it).value;
	return true;
}



YmsgField YMSG::GetField(const string& data,int num,int occur)
{
    dbg_head("YMSG::GetField(const string& data,int num,int occur)");
    string s1,s2;
    s1=data;
    s2="\xC0\x80";
    
	size_t found,found2;
    int fld,occ=0;
    
    while(true){ 
        found=s1.find(s2);//find the delim ending the FieldNum, starting FieldData
        if(found==-1) break;
        string dbg_fld=s1.substr(0,found);
        fld=atoi(dbg_fld.c_str());
        found2=s1.find(s2,found+2);
        
        if(found2==-1) break;// why here? unterminated FieldData is invalid.
        dbgline(dbg_fld);
        if(fld==num || num==-1){
            occ++;
            if(occ==occur)
            {
                YmsgField field(s1.substr(0,found2+2));
                dbgline(field.str);
                ReturnD(field);
            }
        }
        s1.erase(0,found2+2);//erase the FieldData+Delim
    }
    ThrowD(1);
    ReturnD( YmsgField() );
}

bool YMSG::sendMsg(const tYmsgHead& tHeadRef, const YmsgField& f)
{
    head.setRef(tHeadRef);
    head.Ref.contentLength=f.str.length();
    head.Ref.sessionID=0xBaaaBaaa;
    head.translate();
    
    printf(">>> YMSG: %04.4x\r\n",head.Ref.type);
    if(head.Ref.contentLength>0 && !f.assembled) return false;//can't sent unassembled field data
    if(!connection.put((const char*) &head.Dat, 20)) return false;
    return connection.put(f.str,head.Ref.contentLength);
}
bool YMSG::sendMsg(int typ, const YmsgField& f, int sta)
{
    if(typ>-1) head.Ref.type=typ;
    head.Ref.status=sta;
    head.Ref.contentLength=0;
    head.Ref.sessionID=0;//0xBaaaBaaa;//yes, completely arbitrary
    /* TODO (#1#): For some reason, client won't set their SID to the given 
                   SID - YahELite for instance stays 0. Needs 
                   to be investigated and corrected.  Short term fix: use 
                   0. */
    
    //if(f!=0) 
    head.Ref.contentLength=f.str.length();
    head.availRef=true;
    head.availDat=false;
    head.translate();
    
    printf(">>> YMSG: %04.4x\r\n",head.Ref.type);
    if(head.Ref.contentLength>0 && !f.assembled) return false;//can't sent unassembled field data
    if(!connection.put((const char*) &head.Dat, 20)) return false;
    return connection.put(f.str,head.Ref.contentLength);
}

bool YMSG::sendMsg(const YmsgPacket& packet)
{
	YmsgPacket tmpPkt=packet;
	tmpPkt.head.copySession(head);//copy session data from YMSG class session header.

	if(!connection.put((const char*) &tmpPkt.head.Dat, 20)) return false;
    return connection.put(tmpPkt.content,head.Ref.contentLength);
}



bool YMSG::sendClientMsg(string src,const string& dst,const string& txt,bool chat)
{
    dbg_head("Proxy::sendClientMsg(string src,string dst,string txt,bool chat)");
    bool srcnul=(src=="");
    if(srcnul) src="YmsgIRC";
    
    YmsgField fd(4,src);
    if(chat || pmToChat)
    {
        fd+=YmsgField(104,dst);
        fd+=YmsgField(109,src);
        fd+=YmsgField(117,txt);
        fd+=YmsgField(124,"1");
        ReturnD(sendMsg(0x00A8,fd));
    }else{
        fd+=YmsgField(5,dst);
        fd+=YmsgField(14,txt);
        fd+=YmsgField(97,"1");
        ReturnD(sendMsg(0x0006,fd));
    }
}
bool YMSG::sendClientUserlist(bool appendlist)
{
    dbg_head("Proxy::sendClientUserlist(bool appendlist)");
    char countstr[10];
    int count=1;//you, if not using list
    if(appendlist) count=channel.users.size();
    count+=2;//YmsgIRC and Yahoo
    itoa(count,countstr,10);
    
    YmsgField  fd(13,"1");
    fd+=YmsgField(104,channel.name);
    fd+=YmsgField(105,channel.topic);
    fd+=YmsgField(108,countstr);
    fd+=YmsgField(126,"328704");
    fd+=YmsgField(128,"1");//catID
    fd+=YmsgField(129,"1");//rmID
    fd+=YmsgField(130,"AA--");
    fd+=YmsgField(302,"10019");
        fd+=YmsgField(10019,username);
    fd+=YmsgField(303,"10019");
    if(appendlist){
		//list<string>::iterator it;
		//for ( it=channel.users.begin() ; it != channel.users.end(); it++ )
		foreach_list(string,it,channel.users)
		{
                fd+=YmsgField(109,*it);
                fd+=YmsgField(110,"0");
                fd+=YmsgField(111,"neuter");
                fd+=YmsgField(113,"1024");
        }
    }else{
        fd+=YmsgField(109,username);
        fd+=YmsgField(110,"0");
        fd+=YmsgField(111,"neuter");
        fd+=YmsgField(141,username);
        fd+=YmsgField(142,"Connected to YmsgIRC");
        fd+=YmsgField(113,"1024");
    }
    fd+=YmsgField(109,"YmsgIRC");
    fd+=YmsgField(110,"0");
    fd+=YmsgField(141,"YMSG-to-IRC Proxy");
    fd+=YmsgField(142,"System Memory");
    fd+=YmsgField(111,"neuter");
    fd+=YmsgField(113,"1024");
    fd+=YmsgField(109,"YmsgIRC");
    fd+=YmsgField(109,"Yahoo");
    fd+=YmsgField(141,"Messenger Chat Admin");
    ReturnD(sendMsg(0x0098, fd));
}


bool YMSG::respClientMode(const string& src, const string& name, bool& mode, bool hasvalue, bool value)
{
    dbg_head("Proxy::respClientMode(string src, string name, bool& mode, bool hasvalue, bool value)");
    char text[255];
    if(hasvalue)
    {
        mode=value;
        sprintf(text,"%s mode has been changed.",name.c_str());
        if(!sendClientMsg("",src,text,false)) ReturnD(false);
    }
    string statetxt= (mode ? "ON" : "OFF");
    sprintf(text,"%s mode is currently %s.",name.c_str(),statetxt.c_str());
    if(!sendClientMsg("",src,text,false)) ReturnD(false);
    ReturnD(true);
}
bool YMSG::respClientQuery(const string& src,const string& query)
{
    dbg_head("Proxy::respClientMode(Proxy::respClientQuery(string src,string query)");
    using namespace std;
    if(src!=username) ReturnD(true);
    string q(query);
    size_t find=q.find(" ");
    string cmd,val;
    if(find==-1){
        cmd=query;
        val="";
    }else{
        cmd=q.substr(0,find);
        val=q.substr(find+1);
    }
    dbg_do(printf("\n\nCMD [%s] [%s]\n\n",cmd.c_str(),val.c_str()));
    
    //can't Switch-Case a string, sigh.
    string ccmd=cmd.c_str();//do NOT release, these are temporary
    string cval=val.c_str();
    
    bool bPrm=false;
    bool bPrmVal;
    if(cval.length()>0){
        bPrm=true;
        bPrmVal=(cval[0]==0x31);
    }
    
    if(ccmd=="help"){
        string cmds=
        "<b>help</b> - display this message \n"
        "<b>setuser</b> <i>[username]</i> - get/change internal YMSG username, \n"
        "<b>nick</b> <i>[nickname]</i> - get/change your IRC nickname, \n"
        "<b>quote</b> <i>[command]</i> - send raw IRC command, \n"
        "<b>pmtochat</b> <i>[0|1]</i> - change pm-to-chat override mode, \n"
        "<b>striptext</b> <i>[0|1]</i> - strip formatting from outgoing text, \n"
        "<b>nickrefresh</b> <i>[0|1]</i> - refresh a user in the userlist if they change IRC Nicks. \n";
        
        //nickRefresh
        
        bool sent=sendClientMsg("",src,cmds,false);
        //delete[] cmds;
        ReturnD(sent);
    }else if(ccmd=="setuser"){
        if(bPrm){
            username=cval;
            if(!sendClientMsg("",src,"Internal YMSG username changed.",false)) ReturnD(false);
        }
        char text[255];
        sprintf(text,"Internal YMSG username is currently '%s'",username.c_str());
        ReturnD(sendClientMsg("",src,text,false));
    }else if(ccmd=="nick"){
        if(bPrm){
            NwEUsername(username,cval);
            /*irc->nick=cval;
            if(sendIRC(IrcCommand(irc->nick,"","NICK","",false,true)) ){
                if(!sendClientMsg("",src,"IRC nickname changed.",false)) ReturnD(false);
            }else{
                if(!sendClientMsg("",src,"IRC nickname could not be changed.",false)) ReturnD(false);
            }*/
        }
        /*char text[255];
        sprintf(text,"IRC nickname is currently '%s'",irc->nick.c_str());
        ReturnD(sendClientMsg("",src,text,false));*/
    }else if(ccmd=="quote"){
        if(bPrm){
            events.push(NwNotify(NW_DATA,"IRC",ccmd,cval));
            /*bool sent=sendIRC(IrcCommand(cval));
            if(sent)
            {
                ReturnD(sendClientMsg("",src,"IRC command sent.",false));
            }else{
                ReturnD(sendClientMsg("",src,"IRC command sending failed",false));
            }*/
        }
    }
    else if(ccmd=="pmtochat"){
        ReturnD(respClientMode(src,"PM-To-Chat", pmToChat, bPrm, bPrmVal));
    }
    else if(ccmd=="striptext"){
        ReturnD(respClientMode(src,"Strip-Text", stripYmsgFormats, bPrm, bPrmVal));
    }
    else if(ccmd=="nickrefresh"){
        ReturnD(respClientMode(src,"Nick-Refresh", nickRefresh, bPrm, bPrmVal));
    }
    ReturnD(sendClientMsg("",src,"Command syntax not recognized.",false));
}






void YMSG::stepActions()
{
    if(actions.size()<1) return;
    NwNotify n=actions.front();
    
    puts(name + string(":ACTION:") + NwNotifyType_Debug(n.typ)
        +" "+n.sDat[0]+" "+n.sDat[1]+" "+n.sDat[2]
    );
    
	switch(n.typ)
	{
        case NW_CONNINFO:
            dbg(n.sDat[0] + itos(n.iDat[0]));
            listener.set(n.sDat[0],n.iDat[0]);
            break;
        case NW_ULIST_END:
            if(n.cDat[0]==NW_CHECK_CHANNEL) sendClientUserlist(true);
            break;
        case NW_PRIVMSG:
        case NW_CHATMSG:
            sendClientMsg(n.sDat[0],n.sDat[1],n.sDat[2],(n.typ==NW_CHATMSG));
            break;
        case NW_DATA:
            sendMsg(n.iDat[0],YmsgField(n.sDat[0],false));
            break;
        case NW_LOGOUT:
            //*** add logout packets...
            sendClientMsg(NW_RESERVED_USERNAME,username,"*** YMSG - A:LOGOUT");
            NwEDisconnect();
            break;
        case NW_CONNECT://can't open() an accepted connection
            if(listener.sock==INVALID_SOCKET) listener.listn(1);
            break;
        case NW_DISCONNECT:
            sendClientMsg(NW_RESERVED_USERNAME,username,"*** YMSG - A:DISCONNECT");
			break;
        //case NW_USERNAME://NwEChanReplace(channel.name, n.sDat[0], n.sDat[1]);//----------------
		//case NW_LOGIN:
        case NW_ULIST_APPEND:
			//sendMsg(0x0098, const YmsgField& f,
			break;
        case NW_ULIST_REMOVE:
			break;
        //case NW_ULIST_TOPIC:
        //case NW_ULIST_NAME:
        //case NW_ULIST_START:
        //case NW_PASSWORD:
	}
    
    switch(n.typ)
    {
        case NW_DISCONNECT:
        case NW_USERNAME://NwEChanReplace(channel.name, n.sDat[0], n.sDat[1]);//----------------
		case NW_LOGIN:
        case NW_ULIST_APPEND:
        case NW_ULIST_REMOVE:
        case NW_ULIST_TOPIC:
        case NW_ULIST_NAME:
        case NW_ULIST_START:
        case NW_PASSWORD:
        default://default stepAction
            return NwNetwork::stepActions();
    }
    return actions.pop();
}



bool YMSG::checkErrors(int nBytes)
{
    if(nBytes>=0 && connection.error==0) return false;
    if(connection.error==XSAEWOULDBLOCK) return false;// waiting for data
    dbgline(string("IRC Error: ")+itos(connection.error)+" "+itos(nBytes));
    NwEDisconnect(false);
    return true;
}


void YMSG::stepRecv()
{
    int nBytes=0;
    if(connection.sock==INVALID_SOCKET)
    {
        //not connected
        connection.iReset();
        NwEAccept(listener);
    }else{
        connection.buf_nullterminated=false;
        connection.setBufLimit(20);
        nBytes=connection.get(20);
        if(checkErrors(nBytes)) return;
        if(nBytes>0)//will reduce to (ixBuf-iwBuf)+1
        {
            int i=connection.iLastWritten();
            if(i==connection.ixBuf)//last byte of header completed
            {
                dbg_head("head complete");
                
                if(connection.buf[0]!='Y') {
                    puts("not YMSG Data!!!");//*** handle this condition
                    exit(0);
                    return;
                }
                
                head.setDat( (tYmsgHead*) connection.buf );//copy
                
                head.translate();
                int datlen=head.Ref.contentLength;
                string datbuf="";
                if(datlen>0){
                    dbg_head("hasdata");
                    dbgline(itos(head.Dat.contentLength));
                    dbgline(itos(head.Ref.contentLength));
                    
                    
                    connection.buf_nullterminated=true;
                    connection.setBufLimit(0xFFFF);
                    connection.iReset();
                    connection.get(datlen,true);
                    //because of the settings, the byte following recv will always be null.
                    //making buf a c-string.
                    datbuf=(const char*) connection.buf;//copy
                    dbgline(datbuf);
                    dbgline(itos(connection.iwBuf));
                    dbg_foot(0);
                }
////////				YmsgPacket packet(head,datbuf);//******** Use this

                dbgline(itos(connection.iwBuf));
                dbg_head("stepIncoming");
                stepIncoming(datbuf);
                dbg_foot(0);
                connection.iReset();//packet completed, next packet needs to be at front of buffer
                dbg_foot(0);
                if(checkErrors(nBytes)) return;
            }
        }
    } 
}
void YMSG::step(NwStepState state)
{
    switch(state)
    {
        case NW_STEP_BEGIN:
            actions.push(NwNotify(NW_CONNECT));
            break;
        case NW_STEP_END:
            break;
        case NW_STEP:
            stepActions();
            do{
                stepRecv();
            }while(connection.error==0 && connection.sock!=INVALID_SOCKET);//should hit EOF or something
            break;
    }
}
void YMSG::notifyStateText(const string& state)
{
    sendClientMsg(NW_RESERVED_USERNAME,username,string("***YmsgIRC Notification: ")+state,false);
}



void YMSG::stepIncoming(const YmsgPacket& packet)
{
	bool hasdata=packet.contentObject.fields.size() > 0;// ...empty() ?
	printf("<<< YMSG: %04.4x\r\n",packet.head.Ref.type);
	switch(packet.head.Ref.type)
	{
        case 0x004C:
        {
            dbgline("sending 4C");
            if( !sendMsg(0x004C, YmsgField()) ) return;
            dbgline("sent 4C");
            break;
        }
        case 0x0057://asking for challenge
        {
            dbgline("got ChalReq");
            //if(doYmsgChallenge)
            //{
            //send challenge
            if(hasdata) setuser(packet.contentObject,1);
            
			YmsgPacket pktAuth(
					YmsgField(1,username)+
					YmsgField(94,YMSG_DUMMY_CHALLENGE)
				,0x0057);


            dbgline("sending Chal");
            if( !sendMsg(pktAuth) ) return;
            dbgline("sent Chal");
            break;
            //}
        }
        case 0x0054://responding to challenge
        case 0x0226://universal login / WM login
        {
            dbgline("got AuthReq/ChalAnswer");
            NwEUsername(packet.contentObject.getValue(1));

            if(username == "")
            {
                dbgline("--User is NULL!");
                //dbg(datbuf);
            }
            
            dbgline("-AcctInfo fields");
			vector<YmsgField> fields;
			fields+=YmsgField(3,username);
            fields+=YmsgField(89,username);
            fields+=YmsgField(90,"1");
            fields+=YmsgField(149,"AA--");
            fields+=YmsgField(150,"AA--");
            fields+=YmsgField(151,"AA--");
            fields+=YmsgField(192,"16777215");
            fields+=YmsgField(213,"2");
            fields+=YmsgField(216,username);
            fields+=YmsgField(254,".");
            fields+=YmsgField(282,"2");
            fields+=YmsgField(300,"444");
                fields+=YmsgField(440,"0");
            fields+=YmsgField(301,"444");

            dbgline("sending AcctInfo (AuthSuccess)");
            if( !sendMsg(YmsgPacket(fields,0x0055,0))  ) return;
            dbgline("sent AcctInfo");
            
			fields.clear();
			fields=	YmsgList(318,
						 YmsgItem(318,
							 YmsgField(65,"YmsgIRC Group")
							+YmsgList(319,
								 YmsgItem(319,YmsgField(7,NW_RESERVED_USERNAME))
								+YmsgItem(319,YmsgField(7,"NickServ"))
								+YmsgItem(319,YmsgField(7,"username"))
							 ).toFields()
						 )
					 )
					 +YmsgList(320,
						  YmsgItem(320,YmsgField(7,"dummy_ignore_entry0"))
						 +YmsgItem(320,YmsgField(7,"dummy_ignore_entry1"))
					 ).toFields();
			if( !sendMsg(YmsgPacket(fields,0x00F1,0)) ) return;

            dbgline("sent BuddyList");
            
            
			fields.clear();
			fields+=YmsgField(241,0);
			YmsgItem stat(315,
				    YmsgField(7,"")
                   +YmsgField(10,"0")
                   +YmsgField(13,"1")
                   +YmsgField(192,"-1226535179")
                   +YmsgField(198,"0")
                   +YmsgField(213,"2")
                   +YmsgField(244,"16777215")
			);
			YmsgList stats=YmsgList(315);
			stat.fields[0].value=username;
			stat.fields[0].assemble();
			stats.addItem(stat);
			stat.fields[0].value=NW_RESERVED_USERNAME;
			stat.fields[0].assemble();
			stats.addItem(stat);
			fields+=stats.toFields();
			if(!   sendMsg(YmsgPacket(fields, 0x00F0, 0))   ) return;


            
            
            YmsgField  fd3(241,"0");
            fd3+=YmsgField(302,"315");
                fd3+=YmsgField(300,"315");
                    fd3+=YmsgField(7,username);
                    fd3+=YmsgField(10,"0");
                    fd3+=YmsgField(13,"1");
                    fd3+=YmsgField(192,"-1226535179");
                    fd3+=YmsgField(198,"0");
                    fd3+=YmsgField(213,"2");
                    fd3+=YmsgField(244,"16777215");
                fd3+=YmsgField(301,"315");
                fd3+=YmsgField(300,"315");
                    fd3+=YmsgField(7,NW_RESERVED_USERNAME);
                    fd3+=YmsgField(10,"0");
                    fd3+=YmsgField(13,"1");
                    fd3+=YmsgField(192,"-1226535179");
                    fd3+=YmsgField(198,"0");
                    fd3+=YmsgField(213,"2");
                    fd3+=YmsgField(244,"16777215");
                fd3+=YmsgField(301,"315");
                /*fd3+=YmsgField(300,"315");
                    fd3+=YmsgField(7,"NickServ");
                    fd3+=YmsgField(10,"0");
                    fd3+=YmsgField(13,"1");
                    fd3+=YmsgField(192,"-1226535179");
                    fd3+=YmsgField(198,"0");
                    fd3+=YmsgField(213,"2");
                    fd3+=YmsgField(244,"16777215");
                fd3+=YmsgField(301,"315");*/
            fd3+=YmsgField(303,"315");
            if( !sendMsg(0x00F0, fd3,0) ) return;
            
            events.push(NwNotify(NW_LOGIN,username,"",""));
            
            
            /* ***
            pWriteIRC=bufIRC;
            irc->nick=username;
            channel.reset();
            puts("*** Connecting to IRC Server.");
            if(!sendClientMsg("",username,"Connecting to IRC server... Please wait.",false)) return 2;
            if(!openConnect()) return 2;
            if(skConnect!=INVALID_SOCKET){
                puts("*** Connected to IRC Server.");
                if( !sendClientMsg("",username,"Connected to IRC Server. Logging in....",false)) return 2;
                if( !sendIRC(IrcCommand(irc->nick,"","PASS","melzar"          ,false      )) ) return 2;
                if( !sendIRC(IrcCommand(irc->nick,"","NICK",""                 ,false, true)) ) return 2;
                if( !sendIRC(IrcCommand(irc->nick,"","USER","0 * :YmsgIrcUserJustTestingAClient",false, true)) ) return 2;
            }else{
                puts("*** Could not connect to IRC Server!");
            }
            */
            break;
        }
        case 0x0096:
        {
            if(hasdata){
                YmsgField  fd(1,username);
                fd+=YmsgField(6,"abcde");
                fd+=YmsgField(98,"us");
                fd+=YmsgField(109,username);
                fd+=YmsgField(135,YMSG_DUMMY_MSGRVER);
                fd+=YmsgField(302,"10019");
                fd+=YmsgField(10019,username);
                fd+=YmsgField(303,"10019");
                
                NwEChanRemove("", username);
                
                if(!sendMsg(0x0096,fd)) return;
                // *** if(!sendIRC(IrcCommand("JOIN 0"))) return 2;
            }
            break;
        }
        case 0x0098:
        {
            if(hasdata){
                
                NwEChanRemove("", username);
                // *** if(!sendIRC(IrcCommand("JOIN 0"))) return 2;
                
				string dst=packet.contentObject.getValue(104);
                
                NwEChanStart(dst, "");
                NwEChanAppend(dst,username);
                
                //channel.reset();
                //channel.name=dst;
                //IrcCommand ic("","","JOIN",dst);
                //***if( !sendIRC(ic) ) return 2;
            }
            break;
        }
        case 0x009B:
        case 0x00A0:
        {
            string rm="";
            if(hasdata) rm=packet.contentObject.getValue(104);
            NwEChanRemove(rm, username);
            //channel.reset();
            //***if(!sendIRC(IrcCommand("JOIN 0"))) return 2;
            break;
        }
        case 0x0002:
        {
            events.push(NwNotify(NW_LOGOUT));
            //***if(!sendIRC(IrcCommand("QUIT :YmsgIrc client quit"))) return 2;
            break;
        }
        case 0x0006:
        {
            if(hasdata){
                string dst=packet.contentObject.getValue(5);
                string txt_yahoo=packet.contentObject.getValue(14);
                
                
                //strip formatting from 'txt'
                dbg("\r\n {{{ ");
                dbg(txt_yahoo);
                string txt;
                
                
                

                //*** NOTE: for Issue #8, check dst against "YmsgIRC"
                if(dst=="YmsgIRC")
                {
                    txt=RendererText_StripText(txt_yahoo);
                    bool sent=respClientQuery(username,txt);
                    //delstr(&txt_yahoo);
                    //delstr(&txt);
                    //delstr(&dst);
                    if(!sent) return;
                }else{
                    if(stripYmsgFormats) txt=RendererText_StripText(txt_yahoo);
                    else txt=txt_yahoo;
                    
                    dbg(" -> ");
                    dbg(txt);
                    dbg(" }}} \r\n");
                    
                    //IrcCommand (string src,string dst, string typ, string cont,bool singlecont, bool incOrig)
                    
                    //*** NOTE: for Issue #7, 
                    //check dst against username and if it matches change dst to irc->nick.
                    NwEMsg(username,dst, txt);
                    //IrcCommand ic(irc->nick ,dst  ,"PRIVMSG" ,txt ,true);
                    //ic.debug();
                    //*** if( !sendIRC(ic)) return 2;
                    
                    
                }
                
                
            }
            break;
        }
        case 0x00A8:
        {
            if(hasdata){
                string dst=packet.contentObject.getValue(104);
                string txt_yahoo=packet.contentObject.getValue(117);
                
                
                string txt;
                
                if(stripYmsgFormats) txt=RendererText_StripText(txt_yahoo);
                else txt=txt_yahoo;
                
                NwEMsg(username,dst,txt);
                //IrcCommand ic(irc->nick,dst,"PRIVMSG",txt,true);
                //***if( !sendIRC(ic)) return 2;
            }
            break;
        }
    }
}


void YMSG::stepIncoming(const string& datbuf)
{
    bool hasdata=datbuf.length()>0;
    printf("<<< YMSG: %04.4x\r\n",head.Ref.type);
    switch(head.Ref.type)
    {
        case 0x004C:
        {
            dbgline("sending 4C");
            if( !sendMsg(0x004C, YmsgField()) ) return;
            dbgline("sent 4C");
            break;
        }
        case 0x0057://asking for challenge
        {
            dbgline("got ChalReq");
            //if(doYmsgChallenge)
            //{
            //send challenge
            if(hasdata){
                 setuser(datbuf,1);
            }
            
            YmsgField fUser(1,username);
            fUser+=YmsgField(94,YMSG_DUMMY_CHALLENGE);
            
            dbgline("sending Chal");
            if( !sendMsg(0x0057, fUser) ) return;
            dbgline("sent Chal");
            break;
            //}
        }
        case 0x0054://responding to challenge
        case 0x0226://universal login / WM login
        {
            dbgline("got AuthReq/ChalAnswer");
            if(hasdata){
                NwEUsername(getdata(datbuf,1));
            }
            if(username == "")
            {
                dbgline("--User is NULL!");
                dbg(datbuf);
            }
            
            dbgline("-AcctInfo fields");
            
            YmsgField  fd(3,username);
            fd+=YmsgField(89,username);
            fd+=YmsgField(90,"1");
            fd+=YmsgField(149,"AA--");
            fd+=YmsgField(150,"AA--");
            fd+=YmsgField(151,"AA--");
            fd+=YmsgField(192,"16777215");
            fd+=YmsgField(213,"2");
            fd+=YmsgField(216,username);
            fd+=YmsgField(254,".");
            fd+=YmsgField(282,"2");
            fd+=YmsgField(300,"444");
                fd+=YmsgField(440,"0");
            fd+=YmsgField(301,"444");
            //fBuddy+=YmsgField(470,"us");
            dbg(fd.str);
            dbg("\n");
            dbgline("sending AcctInfo (AuthSuccess)");
            if( !sendMsg(0x0055, fd,0) ) return;
            dbgline("sent AcctInfo");
            
            
            YmsgField  fd2(302,"318");
                fd2+=YmsgField(300,"318");
                    fd2+=YmsgField(65,"YmsgIRC");
                    fd2+=YmsgField(302,"319");                            
                        fd2+=YmsgField(300,"319");
                            fd2+=YmsgField(7,NW_RESERVED_USERNAME);
                        fd2+=YmsgField(301,"319");                            
                        fd2+=YmsgField(300,"319");
                            fd2+=YmsgField(7,"NickServ");
                        fd2+=YmsgField(301,"319"); 
                        fd2+=YmsgField(300,"319");
                            fd2+=YmsgField(7,username);
                        fd2+=YmsgField(301,"319");
                    fd2+=YmsgField(303,"319");
                fd2+=YmsgField(301,"318");
            fd2+=YmsgField(303,"318");
            fd2+=YmsgField(302,"320");
                fd2+=YmsgField(300,"320");
                    fd2+=YmsgField(7,"dummy_ignore_entry");
                fd2+=YmsgField(301,"320");
            fd2+=YmsgField(303,"320");
            dbgline("sending BuddyList");
            if( !sendMsg(0x00F1, fd2,0) ) return;
            dbgline("sent BuddyList");
            
            
            
            
            YmsgField  fd3(241,"0");
            fd3+=YmsgField(302,"315");
                fd3+=YmsgField(300,"315");
                    fd3+=YmsgField(7,username);
                    fd3+=YmsgField(10,"0");
                    fd3+=YmsgField(13,"1");
                    fd3+=YmsgField(192,"-1226535179");
                    fd3+=YmsgField(198,"0");
                    fd3+=YmsgField(213,"2");
                    fd3+=YmsgField(244,"16777215");
                fd3+=YmsgField(301,"315");
                fd3+=YmsgField(300,"315");
                    fd3+=YmsgField(7,NW_RESERVED_USERNAME);
                    fd3+=YmsgField(10,"0");
                    fd3+=YmsgField(13,"1");
                    fd3+=YmsgField(192,"-1226535179");
                    fd3+=YmsgField(198,"0");
                    fd3+=YmsgField(213,"2");
                    fd3+=YmsgField(244,"16777215");
                fd3+=YmsgField(301,"315");
                /*fd3+=YmsgField(300,"315");
                    fd3+=YmsgField(7,"NickServ");
                    fd3+=YmsgField(10,"0");
                    fd3+=YmsgField(13,"1");
                    fd3+=YmsgField(192,"-1226535179");
                    fd3+=YmsgField(198,"0");
                    fd3+=YmsgField(213,"2");
                    fd3+=YmsgField(244,"16777215");
                fd3+=YmsgField(301,"315");*/
            fd3+=YmsgField(303,"315");
            if( !sendMsg(0x00F0, fd3,0) ) return;
            
            events.push(NwNotify(NW_LOGIN,username,"",""));
            
            
            /* ***
            pWriteIRC=bufIRC;
            irc->nick=username;
            channel.reset();
            puts("*** Connecting to IRC Server.");
            if(!sendClientMsg("",username,"Connecting to IRC server... Please wait.",false)) return 2;
            if(!openConnect()) return 2;
            if(skConnect!=INVALID_SOCKET){
                puts("*** Connected to IRC Server.");
                if( !sendClientMsg("",username,"Connected to IRC Server. Logging in....",false)) return 2;
                if( !sendIRC(IrcCommand(irc->nick,"","PASS","melzar"          ,false      )) ) return 2;
                if( !sendIRC(IrcCommand(irc->nick,"","NICK",""                 ,false, true)) ) return 2;
                if( !sendIRC(IrcCommand(irc->nick,"","USER","0 * :YmsgIrcUserJustTestingAClient",false, true)) ) return 2;
            }else{
                puts("*** Could not connect to IRC Server!");
            }
            */
            break;
        }
        case 0x0096:
        {
            if(hasdata){
                YmsgField  fd(1,username);
                fd+=YmsgField(6,"abcde");
                fd+=YmsgField(98,"us");
                fd+=YmsgField(109,username);
                fd+=YmsgField(135,YMSG_DUMMY_MSGRVER);
                fd+=YmsgField(302,"10019");
                fd+=YmsgField(10019,username);
                fd+=YmsgField(303,"10019");
                
                NwEChanRemove("", username);
                
                if(!sendMsg(0x0096,fd)) return;
                // *** if(!sendIRC(IrcCommand("JOIN 0"))) return 2;
            }
            break;
        }
        case 0x0098:
        {
            if(hasdata){
                
                NwEChanRemove("", username);
                // *** if(!sendIRC(IrcCommand("JOIN 0"))) return 2;
                
                string dst;
                try{
                    dst=getdata(datbuf,104);
                }
                CatchD(...)
                    string etxt="Exception Caught: Location info: 0x0098 string dst=getdata(datbuf,104);";
                    puts(etxt);
                }
                
                NwEChanStart(dst, "");
                NwEChanAppend(dst,username);
                
                //channel.reset();
                //channel.name=dst;
                //IrcCommand ic("","","JOIN",dst);
                //***if( !sendIRC(ic) ) return 2;
            }
            break;
        }
        case 0x009B:
        case 0x00A0:
        {
            string rm="";
            if(hasdata) rm=getdata(datbuf,104);
            NwEChanRemove(rm, username);
            //channel.reset();
            //***if(!sendIRC(IrcCommand("JOIN 0"))) return 2;
            break;
        }
        case 0x0002:
        {
            events.push(NwNotify(NW_LOGOUT));
            //***if(!sendIRC(IrcCommand("QUIT :YmsgIrc client quit"))) return 2;
            break;
        }
        case 0x0006:
        {
            if(hasdata){
                string dst;
                try{
                    dst=getdata(datbuf,5);
                }
                CatchD(...)
                    string etxt="Exception Caught: Location info: 0x0006 string dst=getdata(datbuf,5);";
                    puts(etxt);
                }
                
                string txt_yahoo;
                try{
                    txt_yahoo=getdata(datbuf,14);
                }
                CatchD(...)
                    string etxt="Exception Caught: Location info: 0x0006 string dst=getdata(datbuf,14);";
                    puts(etxt);
                }
                
                
                //strip formatting from 'txt'
                dbg("\r\n {{{ ");
                dbg(txt_yahoo);
                string txt;
                
                
                

                //*** NOTE: for Issue #8, check dst against "YmsgIRC"
                if(dst=="YmsgIRC")
                {
                    txt=RendererText_StripText(txt_yahoo);
                    bool sent=respClientQuery(username,txt);
                    //delstr(&txt_yahoo);
                    //delstr(&txt);
                    //delstr(&dst);
                    if(!sent) return;
                }else{
                    if(stripYmsgFormats) txt=RendererText_StripText(txt_yahoo);
                    else txt=txt_yahoo;
                    
                    dbg(" -> ");
                    dbg(txt);
                    dbg(" }}} \r\n");
                    
                    //IrcCommand (string src,string dst, string typ, string cont,bool singlecont, bool incOrig)
                    
                    //*** NOTE: for Issue #7, 
                    //check dst against username and if it matches change dst to irc->nick.
                    NwEMsg(username,dst, txt);
                    //IrcCommand ic(irc->nick ,dst  ,"PRIVMSG" ,txt ,true);
                    //ic.debug();
                    //*** if( !sendIRC(ic)) return 2;
                    
                    
                }
                
                
            }
            break;
        }
        case 0x00A8:
        {
            if(hasdata){
                string dst;
                try{
                    dst=getdata(datbuf,104);
                }
                CatchD(...)
                    string etxt="Exception Caught: Location info: 0x00A8 string dst=getdata(datbuf,104);";
                    puts(etxt);
                }
                
                
                string txt_yahoo;
                try{
                    txt_yahoo=getdata(datbuf,117);
                }
                CatchD(...)
                    string etxt="Exception Caught: Location info: 0x00A8 string dst=getdata(datbuf,117);";
                    puts(etxt);
                }
                
                
                string txt;
                
                if(stripYmsgFormats) txt=RendererText_StripText(txt_yahoo);
                else txt=txt_yahoo;
                
                NwEMsg(username,dst,txt);
                //IrcCommand ic(irc->nick,dst,"PRIVMSG",txt,true);
                //***if( !sendIRC(ic)) return 2;
            }
            break;
        }
    }
}

